<template>
  <div class="app-container">
    <el-card class="box-card">
      <div slot="header" class="clearfix">
        <span><i class="el-icon-connection"></i> Modbus通信测试</span>
      </div>
      
      <!-- 设备配置区域 -->
      <el-row :gutter="20">
        <el-col :span="12">
          <el-card shadow="never">
            <div slot="header">设备配置</div>
            <el-form :model="deviceForm" ref="deviceForm" label-width="120px" size="small">
              <el-form-item label="设备编码" prop="deviceSN">
                <el-input v-model="deviceForm.deviceSN" placeholder="请输入设备ID" />
              </el-form-item>
              <el-form-item label="设备名称" prop="deviceName">
                <el-input v-model="deviceForm.deviceName" placeholder="请输入设备名称" />
              </el-form-item>
              <el-form-item label="设备类型" prop="deviceType">
                <el-radio-group v-model="deviceForm.deviceType" @change="handleDeviceTypeChange">
                  <el-radio label="TCP">TCP</el-radio>
                  <el-radio label="RTU">RTU</el-radio>
                </el-radio-group>
              </el-form-item>
              
              <!-- TCP配置 -->
              <div v-if="deviceForm.deviceType === 'TCP'">
                <el-form-item label="IP地址" prop="ipAddress">
                  <el-input v-model="deviceForm.ipAddress" placeholder="192.168.1.100">
                    <el-button slot="append" @click="refreshLocalIP" title="刷新本机IP地址">
                      <i class="el-icon-refresh"></i>
                    </el-button>
                  </el-input>
                  <div style="font-size: 12px; color: #909399; margin-top: 5px;">
                    <i class="el-icon-info"></i> 
                    当前IP: {{ deviceForm.ipAddress }} 
                    <el-tag size="mini" type="info" v-if="ipSource">{{ ipSource }}</el-tag>
                    <br>
                    <span style="font-size: 11px;">💡 可手动修改或点击刷新按钮自动获取</span>
                  </div>
                  
                  <!-- IP地址选择下拉框 -->
                  <div v-if="availableIPs.length > 1" style="margin-top: 10px;">
                    <el-select 
                      v-model="deviceForm.ipAddress" 
                      placeholder="选择其他IP地址" 
                      size="small" 
                      style="width: 100%"
                      @change="handleIPChange">
                      <el-option 
                        v-for="ipInfo in availableIPs" 
                        :key="ipInfo.ip" 
                        :label="`${ipInfo.ip} (${ipInfo.type} - ${ipInfo.interface})`" 
                        :value="ipInfo.ip">
                        <span style="float: left">{{ ipInfo.ip }}</span>
                        <span style="float: right; color: #8492a6; font-size: 13px">
                          {{ ipInfo.type }} - {{ ipInfo.interface }}
                        </span>
                      </el-option>
                    </el-select>
                  </div>
                </el-form-item>
                <el-form-item label="端口" prop="port">
                  <el-input-number v-model="deviceForm.port" :min="1" :max="65535" />
                </el-form-item>
              </div>
              
              <!-- RTU配置 -->
              <div v-if="deviceForm.deviceType === 'RTU'">
                <el-form-item label="串口" prop="serialPort">
                  <el-select v-model="deviceForm.serialPort" placeholder="请选择串口" filterable>
                    <el-option v-for="port in availablePorts" :key="port" :label="port" :value="port" />
                  </el-select>
                </el-form-item>
                <el-form-item label="波特率" prop="baudRate">
                  <el-select v-model="deviceForm.baudRate">
                    <el-option label="9600" :value="9600" />
                    <el-option label="19200" :value="19200" />
                    <el-option label="38400" :value="38400" />
                    <el-option label="57600" :value="57600" />
                    <el-option label="115200" :value="115200" />
                  </el-select>
                </el-form-item>
                <el-row :gutter="10">
                  <el-col :span="8">
                    <el-form-item label="数据位">
                      <el-select v-model="deviceForm.dataBits">
                        <el-option label="7" :value="7" />
                        <el-option label="8" :value="8" />
                      </el-select>
                    </el-form-item>
                  </el-col>
                  <el-col :span="8">
                    <el-form-item label="停止位">
                      <el-select v-model="deviceForm.stopBits">
                        <el-option label="1" :value="1" />
                        <el-option label="2" :value="2" />
                      </el-select>
                    </el-form-item>
                  </el-col>
                  <el-col :span="8">
                    <el-form-item label="校验位">
                      <el-select v-model="deviceForm.parity">
                        <el-option label="无" value="NONE" />
                        <el-option label="奇" value="ODD" />
                        <el-option label="偶" value="EVEN" />
                      </el-select>
                    </el-form-item>
                  </el-col>
                </el-row>
              </div>
              
              <el-form-item label="超时时间(ms)" prop="timeout">
                <el-input-number v-model="deviceForm.timeout" :min="1000" :max="30000" />
              </el-form-item>
              
              <el-form-item>
                <el-button type="primary" @click="testConnection" :loading="connectionTesting">
                  <i class="el-icon-connection"></i> 测试连接
                </el-button>
                <el-button @click="resetDeviceForm">重置</el-button>
              </el-form-item>
            </el-form>
          </el-card>
        </el-col>
        
        <el-col :span="12">
          <el-card shadow="never">
            <div slot="header">操作配置</div>
            <el-form :model="operationForm" ref="operationForm" label-width="120px" size="small">
              <el-form-item label="功能码" prop="functionCode">
                <el-select v-model="operationForm.functionCode" @change="handleFunctionCodeChange">
                  <el-option label="读线圈(01)" value="COILS" />
                  <el-option label="读离散输入(02)" value="DISCRETE_INPUTS" />
                  <el-option label="读保持寄存器(03)" value="HOLDING_REGISTERS" />
                  <el-option label="读输入寄存器(04)" value="INPUT_REGISTERS" />
                  <el-option label="写单个线圈(05)" value="WRITE_SINGLE_COIL" />
                  <el-option label="写单个寄存器(06)" value="WRITE_SINGLE_REGISTER" />
                </el-select>
              </el-form-item>
              <el-form-item label="起始地址" prop="startAddress">
                <el-input-number v-model="operationForm.startAddress" :min="0" :max="65535" />
              </el-form-item>
              <el-form-item v-if="isReadOperation" label="数量" prop="quantity">
                <el-input-number v-model="operationForm.quantity" :min="1" :max="125" />
              </el-form-item>
              <el-form-item v-if="isWriteOperation" label="写入值" prop="value">
                <el-input v-model="operationForm.value" placeholder="请输入要写入的值" />
              </el-form-item>
              <el-form-item label="从站地址" prop="slaveAddress">
                <el-input-number v-model="operationForm.slaveAddress" :min="1" :max="247" />
              </el-form-item>
              
              <el-form-item>
                <el-button type="success" @click="executeOperation" :loading="operationExecuting">
                  <i class="el-icon-video-play"></i> 执行操作
                </el-button>
                <el-button @click="resetOperationForm">重置</el-button>
              </el-form-item>
            </el-form>
          </el-card>
        </el-col>
      </el-row>
      
      
      
      <!-- 结果显示区域 -->
      <el-row :gutter="20" style="margin-top: 20px;">
        <el-col :span="24">
          <el-card shadow="never">
            <div slot="header">
              <span>执行结果</span>
              <el-button style="float: right; padding: 3px 0" type="text" @click="clearResults">
                <i class="el-icon-delete"></i> 清空
              </el-button>
            </div>
            <div v-if="results.length === 0" class="text-center" style="color: #999; padding: 20px;">
              暂无执行结果
            </div>
            <div v-for="(result, index) in results" :key="index" class="result-item">
              <div class="result-header">
                <span class="result-time">{{ result.timestamp }}</span>
                <el-tag :type="result.success ? 'success' : 'danger'" size="mini">
                  {{ result.success ? '成功' : '失败' }}
                </el-tag>
                <span class="result-operation">{{ result.operation }}</span>
              </div>
              <div class="result-content">
                <pre v-if="result.success">{{ JSON.stringify(result.data, null, 2) }}</pre>
                <div v-else class="error-message">{{ result.error }}</div>
              </div>
            </div>
          </el-card>
        </el-col>
      </el-row>
    </el-card>
  </div>
</template>

<script>
import { 
  testRtuConnection, testTcpConnection,
  readRtuHoldingRegisters, readTcpHoldingRegisters,
  readRtuInputRegisters, readTcpInputRegisters,
  readRtuCoils, readTcpCoils,
  readRtuDiscreteInputs, readTcpDiscreteInputs,
  writeRtuSingleCoil, writeTcpSingleCoil,
  writeRtuSingleRegister, writeTcpSingleRegister,
  getAvailableSerialPorts
} from "@/api/business/modbus"

import { getLocalIPAddresses, refreshLocalIPAddresses } from "@/api/business/system"

export default {
  name: "ModbusTest",
  data() {
    return {
      // 设备配置表单
      deviceForm: {
        deviceSN: 'test_device_001',
        deviceName: '测试设备',
        deviceType: 'TCP',
        ipAddress: '192.168.1.100',
        port: 502,
        serialPort: 'COM1',
        baudRate: 9600,
        dataBits: 8,
        stopBits: 1,
        parity: 'NONE',
        timeout: 3000
      },
      // 操作配置表单
      operationForm: {
        functionCode: 'HOLDING_REGISTERS',
        startAddress: 0,
        quantity: 1,
        value: '',
        slaveAddress: 1
      },
      // 执行结果
      results: [],
      // 可用串口列表
      availablePorts: [],
      // 加载状态
      connectionTesting: false,
      operationExecuting: false,
      
      ipSource: '', // 新增：用于存储IP地址的来源
      availableIPs: [] // 新增：用于存储所有可用的IP地址
    }
  },
  computed: {
    isReadOperation() {
      return ['COILS', 'DISCRETE_INPUTS', 'HOLDING_REGISTERS', 'INPUT_REGISTERS'].includes(this.operationForm.functionCode)
    },
    isWriteOperation() {
      return ['WRITE_SINGLE_COIL', 'WRITE_SINGLE_REGISTER'].includes(this.operationForm.functionCode)
    }
  },
  created() {
    this.getAvailablePorts()
    
    this.getLocalIPAddress()
    
    // 显示IP地址获取提示
    this.$nextTick(() => {
      if (this.deviceForm.deviceType === 'TCP') {
        this.$message({
          message: `已自动获取本机IP地址: ${this.deviceForm.ipAddress} (${this.ipSource})`,
          type: 'info',
          duration: 3000
        })
      }
    })
  },
  methods: {
    /** 获取可用串口列表 */
    getAvailablePorts() {
      getAvailableSerialPorts().then(response => {
        this.availablePorts = response.data || ['COM1', 'COM2', 'COM3']
      }).catch(() => {
        this.availablePorts = ['COM1', 'COM2', 'COM3']
      })
    },
    
    /** 获取本机IP地址 */
    async getLocalIPAddress() {
      try {
        const response = await getLocalIPAddresses()
        if (response.code === 200 && response.data) {
          // 保存所有可用的IP地址
          this.availableIPs = response.data.ipList || []
          
          // 使用推荐的IP地址
          if (response.data.recommendedIP) {
            this.deviceForm.ipAddress = response.data.recommendedIP
            this.ipSource = '后端推荐'
          } else if (this.availableIPs.length > 0) {
            // 如果没有推荐IP，使用第一个内网IP
            const firstIP = this.availableIPs[0]
            this.deviceForm.ipAddress = firstIP.ip
            this.ipSource = `后端(${firstIP.type})`
          } else {
            this.deviceForm.ipAddress = '127.0.0.1'
            this.ipSource = '默认'
          }
        } else {
          this.deviceForm.ipAddress = '127.0.0.1'
          this.ipSource = '默认'
          this.availableIPs = []
        }
      } catch (error) {
        console.warn('获取本机IP地址失败:', error)
        this.deviceForm.ipAddress = '127.0.0.1'
        this.ipSource = '默认'
        this.availableIPs = []
      }
    },
    
    /** 刷新本机IP地址 */
    async refreshLocalIP() {
      this.ipSource = '获取中...'
      this.availableIPs = []
      
      try {
        // 先尝试刷新缓存
        await refreshLocalIPAddresses()
        this.$message.success('IP地址缓存刷新成功')
      } catch (error) {
        console.warn('刷新缓存失败，使用普通获取:', error)
      }
      
      // 获取最新的IP地址
      await this.getLocalIPAddress()
      this.$message.success('本机IP地址已更新')
    },

    /** 处理IP地址选择变化 */
    handleIPChange(value) {
      const selectedIP = this.availableIPs.find(ip => ip.ip === value);
      if (selectedIP) {
        this.ipSource = `${selectedIP.type} - ${selectedIP.interface}`;
      } else {
        this.ipSource = '未知来源';
      }
    },
    
    /** 设备类型改变 */
    handleDeviceTypeChange() {
      if (this.deviceForm.deviceType === 'TCP') {
        // 使用当前的本机IP地址，如果没有则使用默认值
        this.deviceForm.ipAddress = this.deviceForm.ipAddress || '127.0.0.1'
        this.deviceForm.port = 502
      } else {
        this.deviceForm.serialPort = 'COM1'
        this.deviceForm.baudRate = 9600
      }
    },
    
    /** 功能码改变 */
    handleFunctionCodeChange() {
      if (this.isReadOperation) {
        this.operationForm.quantity = 1
        this.operationForm.value = ''
      } else {
        this.operationForm.quantity = null
        this.operationForm.value = this.operationForm.functionCode === 'WRITE_SINGLE_COIL' ? 'true' : '100'
      }
    },
    
    /** 测试连接 */
    async testConnection() {
      this.connectionTesting = true
      try {
        const deviceData = this.buildDeviceData()
        let response
        
        if (this.deviceForm.deviceType === 'TCP') {
          response = await testTcpConnection(deviceData)
        } else {
          response = await testRtuConnection(deviceData)
        }
        
        // 根据后端返回的实际结果判断是否成功
        const isSuccess = response.data === true
        this.addResult('测试连接', response.data, isSuccess)
        
        if (isSuccess) {
          this.$message.success('连接测试成功')
        } else {
          this.$message.error('连接测试失败')
        }
      } catch (error) {
        this.addResult('测试连接', error.message, false)
        this.$message.error('连接测试失败')
      } finally {
        this.connectionTesting = false
      }
    },
    
    /** 执行操作 */
    async executeOperation() {
      this.operationExecuting = true
      try {
        const deviceData = this.buildDeviceData()
        const operationData = {
          ...deviceData,
          startAddress: this.operationForm.startAddress,
          quantity: this.operationForm.quantity,
          value: this.operationForm.value,
          slaveAddress: this.operationForm.slaveAddress
        }
        
        let response
        const operation = this.operationForm.functionCode
        
        if (this.deviceForm.deviceType === 'TCP') {
          response = await this.executeTcpOperation(operation, operationData)
        } else {
          response = await this.executeRtuOperation(operation, operationData)
        }
        
        this.addResult(this.getOperationName(operation), response.data, true)
        this.$message.success('操作执行成功')
      } catch (error) {
        this.addResult(this.getOperationName(this.operationForm.functionCode), error.message, false)
        this.$message.error('操作执行失败')
      } finally {
        this.operationExecuting = false
      }
    },
    
    /** 执行TCP操作 */
    async executeTcpOperation(operation, data) {
      switch (operation) {
        case 'HOLDING_REGISTERS':
          return await readTcpHoldingRegisters(data)
        case 'INPUT_REGISTERS':
          return await readTcpInputRegisters(data)
        case 'COILS':
          return await readTcpCoils(data)
        case 'DISCRETE_INPUTS':
          return await readTcpDiscreteInputs(data)
        case 'WRITE_SINGLE_COIL':
          return await writeTcpSingleCoil(data)
        case 'WRITE_SINGLE_REGISTER':
          return await writeTcpSingleRegister(data)
        default:
          throw new Error('不支持的操作类型')
      }
    },
    
    /** 执行RTU操作 */
    async executeRtuOperation(operation, data) {
      switch (operation) {
        case 'HOLDING_REGISTERS':
          return await readRtuHoldingRegisters(data)
        case 'INPUT_REGISTERS':
          return await readRtuInputRegisters(data)
        case 'COILS':
          return await readRtuCoils(data)
        case 'DISCRETE_INPUTS':
          return await readRtuDiscreteInputs(data)
        case 'WRITE_SINGLE_COIL':
          return await writeRtuSingleCoil(data)
        case 'WRITE_SINGLE_REGISTER':
          return await writeRtuSingleRegister(data)
        default:
          throw new Error('不支持的操作类型')
      }
    },
    
    /** 构建设备数据 */
    buildDeviceData() {
      return {
        deviceSN: this.deviceForm.deviceSN,
        deviceName: this.deviceForm.deviceName,
        deviceType: this.deviceForm.deviceType,
        ipAddress: this.deviceForm.ipAddress,
        port: this.deviceForm.port,
        serialPort: this.deviceForm.serialPort,
        baudRate: this.deviceForm.baudRate,
        dataBits: this.deviceForm.dataBits,
        stopBits: this.deviceForm.stopBits,
        parity: this.deviceForm.parity,
        timeout: this.deviceForm.timeout
      }
    },
    
    
    /** 添加结果 */
    addResult(operation, data, success) {
      this.results.unshift({
        timestamp: this.parseTime(new Date(), '{y}-{m}-{d} {h}:{i}:{s}'),
        operation: operation,
        success: success,
        data: success ? data : null,
        error: success ? null : data
      })
      
      // 保持最多50条记录
      if (this.results.length > 50) {
        this.results = this.results.slice(0, 50)
      }
    },
    
    /** 清空结果 */
    clearResults() {
      this.results = []
    },
    
    /** 重置设备表单 */
    resetDeviceForm() {
      // 获取当前的本机IP地址
      const currentIP = this.deviceForm.ipAddress || '127.0.0.1'
      
      this.deviceForm = {
        deviceSN: 'test_device_001',
        deviceName: '测试设备',
        deviceType: 'TCP',
        ipAddress: currentIP,
        port: 502,
        serialPort: 'COM1',
        baudRate: 9600,
        dataBits: 8,
        stopBits: 1,
        parity: 'NONE',
        timeout: 3000
      }
    },
    
    /** 重置操作表单 */
    resetOperationForm() {
      this.operationForm = {
        functionCode: 'HOLDING_REGISTERS',
        startAddress: 0,
        quantity: 1,
        value: '',
        slaveAddress: 1
      }
    },
    
    /** 获取操作名称 */
    getOperationName(operation) {
      const names = {
        'HOLDING_REGISTERS': '读保持寄存器',
        'INPUT_REGISTERS': '读输入寄存器',
        'COILS': '读线圈',
        'DISCRETE_INPUTS': '读离散输入',
        'WRITE_SINGLE_COIL': '写单个线圈',
        'WRITE_SINGLE_REGISTER': '写单个寄存器'
      }
      return names[operation] || operation
    }
  }
}
</script>

<style scoped>
.result-item {
  border: 1px solid #e4e7ed;
  border-radius: 4px;
  margin-bottom: 10px;
}

.result-header {
  background-color: #f5f7fa;
  padding: 10px 15px;
  border-bottom: 1px solid #e4e7ed;
  display: flex;
  align-items: center;
}

.result-time {
  color: #909399;
  font-size: 12px;
  margin-right: 10px;
}

.result-operation {
  margin-left: 10px;
  font-weight: bold;
}

.result-content {
  padding: 15px;
}

.result-content pre {
  background-color: #f8f9fa;
  border: 1px solid #e9ecef;
  border-radius: 4px;
  padding: 10px;
  margin: 0;
  white-space: pre-wrap;
  word-wrap: break-word;
  font-family: 'Courier New', monospace;
  font-size: 12px;
  max-height: 300px;
  overflow-y: auto;
}

.error-message {
  color: #f56c6c;
  background-color: #fef0f0;
  border: 1px solid #fbc4c4;
  border-radius: 4px;
  padding: 10px;
}

.text-center {
  text-align: center;
}
</style>
